﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FrameworkLib.Facades;
using GestionePolveri2.DAL;
using GestionePolveriLib.BL;
using FrameworkLib.Filters;
using LinqKit;

namespace GestionePolveriLib.Facades
{
    public class ScortaMinimaFacade : FacadeBase<GestionePolveriEntities>
    {
        GestionePolveriEntities context = null;

        public ScortaMinimaFacade()
        {
            context = this.GetContext();
        }

        public List<ScortaMinimaInfo> GetScortaMinimaInfo()
        {
            List<ScortaMinimaInfo> retValue = null;

            try
            {
                double nullValue = 0;

                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri
                          join ll in context.Lotti on x.IDPolvere equals ll.IDPolvere
                          where ll.Giacenza != 0 
                          group x by new { x.CodicePolvere, x.Descrizione, x.Note, x.ScortaMinima, x.IsCodiceCustom, x.IDFornitore, x.IDPolvere } into grp                          
                          orderby grp.Key.CodicePolvere
                          select new ScortaMinimaInfo
                          {
                              ID = grp.Key.IDPolvere,
                              CodicePolvere = grp.Key.CodicePolvere,
                              Descrizione = grp.Key.Descrizione,
                              Note = grp.Key.Note,
                              ScortaMinima = grp.Key.ScortaMinima,
                              //DataControllo = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere orderby l.DataControllo descending select l.DataControllo).FirstOrDefault(),
                              Giacenza = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.Giacenza).Sum(),
                              //Valore = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere  select l.Valore).Sum(),
                              Prezzo = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere  orderby l.DataDdt descending select l.PrezzoUnitario).FirstOrDefault(),
                              Carico = (from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "C")) select m.Quantita).Sum(),
                              Scarico = ((from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Any() ?
                                         (from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Sum() : 0),
                              IsCodiceCustom = grp.Key.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == grp.Key.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                if (obj.Any())
                {
                    retValue = obj.ToList();
                    LoadInformazioniAccessorie(retValue);
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        private double? GetGiacenza(int idPolvere)
        {
            return (from l in context.Lotti where l.IDPolvere == idPolvere   select l.Giacenza).Sum();
        }

        public List<ScortaMinimaInfo> GetScortaMinimaInfo(FilterBase<AnagPolveri> filter)
        {
            List<ScortaMinimaInfo> retValue = null;

            string ff = ((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).Famiglia;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri.AsExpandable().Where(filter.SetUpFilter())
                          join ll in context.Lotti on x.IDPolvere equals ll.IDPolvere
                          //join pr in context.Prenotazioni on x.IDPolvere equals pr.IDPolvere
                          //join fcxp in context.vw_FamiglieColoriXPolveri on x.IDPolvere equals fcxp.idpolvere
                          //where (((ff == null) || (fcxp.Famiglia == ff)))
                          group x by new { x.CodicePolvere, x.Descrizione, x.Note, x.ScortaMinima, x.IsCodiceCustom, x.IDFornitore, x.IDPolvere, x.TipologieScortaMinimaPolvere.IDTipologiaScortaMinimaPolvere } into grp
                          orderby grp.Key.CodicePolvere
                          select new ScortaMinimaInfo
                          {
                              ID = grp.Key.IDPolvere,
                              CodicePolvere = grp.Key.CodicePolvere,
                              Descrizione = grp.Key.Descrizione,
                              Note = grp.Key.Note,
                              ScortaMinima = grp.Key.ScortaMinima,
                              TipologiaSM = (from l in context.TipologieScortaMinimaPolvere where l.IDTipologiaScortaMinimaPolvere == grp.Key.IDTipologiaScortaMinimaPolvere 
                                             select new TipologiaScortaMinima { ID=l.IDTipologiaScortaMinimaPolvere, Codice=l.Codice, Descrizione=l.Descrizione }).FirstOrDefault(),
                              //DataControllo = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere  orderby l.DataControllo descending select l.DataControllo).FirstOrDefault(),
                              Giacenza = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.Giacenza).Sum(),
                              //Valore = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.Giacenza).Sum() * 
                              //         (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere orderby l.DataDdt descending select l.PrezzoUnitario).FirstOrDefault(),
                              Prezzo = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere orderby l.DataDdt descending select l.PrezzoUnitario).FirstOrDefault(),
                              Carico = (from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "C")) select m.Quantita).Sum(),
                              Scarico = ((from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Any() ?
                                         (from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Sum() : 0),
                              //CodLotto = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.CodLotto).FirstOrDefault(),
                              DataControllo = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere orderby l.DataControllo descending select l.DataControllo).FirstOrDefault(),
                              NoteCarico = (from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "C")) select m.Note).FirstOrDefault(),
                              IsCodiceCustom = grp.Key.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == grp.Key.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault(),
                              QuantitaImpegnata = (from pr in context.Prenotazioni where pr.IDPolvere == grp.Key.IDPolvere && !pr.IsAnnullata select pr.Quantita).Sum(),
                              QuantitaNC = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere && l.LottiNC.FlagNC select l.Giacenza).Sum(),
                              QuantitaNCBlocked = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere && l.LottiNC.FlagBlocco select l.Giacenza).Sum(),
                              CaricoScaricoDiff = ((from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.Giacenza).Sum() -
                                                   (from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "C")) select m.Quantita).Sum() +
                                                   ((from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Any() ?
                                                    (from m in context.Movimenti where ((m.IDPolvere == grp.Key.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Sum() : 0)),
                              DataRiordino = (from dr in context.OrdersDates orderby dr.OrderDate descending where dr.IDPolvere == grp.Key.IDPolvere select dr.OrderDate).FirstOrDefault(),
                              DataChiusuraRiordino = (from dr in context.OrdersDates orderby dr.OrderDate descending where dr.IDPolvere == grp.Key.IDPolvere select dr.OrderCloseDate).FirstOrDefault(),
                              IsGeneratedByCorrection = (from dr in context.OrdersDates orderby dr.OrderDate descending where dr.IDPolvere == grp.Key.IDPolvere select dr.IsGeneratedByCorrection).FirstOrDefault(),
                          };

                if (obj.Any())
                {
                    /* metodo 1 */
                    retValue = obj.ToList();

                    if ((((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere != null) &&
                        (((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere != GestionePolveriLib.BL.FilterBags.PolvereStatus.Tutte.ToString()))
                    {

                        List<ScortaMinimaInfo> aaa = null;
                        List<ScortaMinimaInfo> bbb = null;
                        List<ScortaMinimaInfo> ccc = null;
                        if (((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere.Replace(" ", "").Contains(GestionePolveriLib.BL.FilterBags.PolvereStatus.SottoScorta.ToString()))
                        {
                            aaa = retValue.Where(x => x.QuantitaDisponibile < x.ScortaMinima).ToList();
                        }

                        if (((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere.Replace(" ", "").Contains(GestionePolveriLib.BL.FilterBags.PolvereStatus.InRiordino.ToString()))
                        {
                            bbb = retValue.Where(x => x.DataRiordino != null).ToList();
                        }

                        if (((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere.Replace(" ", "").Contains(GestionePolveriLib.BL.FilterBags.PolvereStatus.GeneratoDaCorrezione.ToString()))
                        {
                            ccc = retValue.Where(x => x.DataChiusuraRiordino != null).ToList();
                        }

                        retValue.Clear();
                        if (aaa != null) retValue.AddRange(aaa);
                        if (bbb != null) retValue.AddRange(bbb);
                        if (ccc != null) retValue.AddRange(ccc);
                    }

                    /* metodo 2*/
                    //if (((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere != null)
                    //{
                    //    var predicate = PredicateBuilder.True<ScortaMinimaInfo>();

                    //    if (((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere.Replace(" ", "").Contains(GestionePolveriLib.BL.FilterBags.PolvereStatus.SottoScorta.ToString()))
                    //    {
                    //        predicate = predicate.And(p => p.Giacenza - (p.QuantitaImpegnata.HasValue ? p.QuantitaImpegnata.Value : 0) - (p.QuantitaNCBlocked.HasValue ? p.QuantitaNCBlocked.Value : 0) < p.ScortaMinima);
                    //    }

                    //    if (((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).StatoPolvere.Replace(" ", "").Contains(GestionePolveriLib.BL.FilterBags.PolvereStatus.InRiordino.ToString()))
                    //    {
                    //        predicate = predicate.And(p => p.DataRiordino != null);
                    //    }

                    //    retValue = obj.Where(predicate).ToList();
                    //}
                    //else
                    //{
                    //    retValue = obj.ToList();
                    //}


                    LoadInformazioniAccessorie(retValue);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return retValue;
        }

        public List<ScortaMinimaInfo> GetScortaMinimaInfo2(FilterBase<AnagPolveri> filter)
        {
            List<ScortaMinimaInfo> retValue = null;

            string ff = ((GestionePolveriLib.BL.FilterBags.VerniciatoreScortaMinimaFilterBag)filter).Famiglia;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri.AsExpandable().Where(filter.SetUpFilter())
                          join ll in context.Lotti on x.IDPolvere equals ll.IDPolvere
                          where ll.Giacenza != 0
                          orderby x.CodicePolvere
                          select new ScortaMinimaInfo
                          {
                              ID = x.IDPolvere,
                              CodicePolvere = x.CodicePolvere,
                              Descrizione = x.Descrizione,
                              Note = x.Note,
                              ScortaMinima = x.ScortaMinima,
                              Giacenza = ll.Giacenza,
                              Prezzo = ll.PrezzoUnitario,
                              Carico = (from m in context.Movimenti where ((m.IDPolvere == x.IDPolvere) && (m.CausaliMagazzino.CodCausale == "C")) select m.Quantita).Sum(),
                              Scarico = ((from m in context.Movimenti where ((m.IDPolvere == x.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Any() ?
                                         (from m in context.Movimenti where ((m.IDPolvere == x.IDPolvere) && (m.CausaliMagazzino.CodCausale == "S")) select m.Quantita).Sum() : 0),
                              CodLotto = ll.CodLotto,
                              DataControllo = ll.DataControllo,
                              NoteCarico = (from m in context.Movimenti where ((m.IDPolvere == x.IDPolvere) && (m.CausaliMagazzino.CodCausale == "C")) select m.Note).FirstOrDefault(),
                              IsCodiceCustom = x.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == x.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                if (obj.Any())
                {
                    retValue = obj.ToList();
                    LoadInformazioniAccessorie(retValue);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return retValue;
        }

        private void LoadInformazioniAccessorie(List<ScortaMinimaInfo> retValue)
        {
            List<LookUp_FamiglieColori_ColoriAbbinati_Result> mmm = (List<LookUp_FamiglieColori_ColoriAbbinati_Result>)FrameworkLib.Utilities.Singleton<GestionePolveriLib.Cache.LookUpData>.Instance.GetData("LookupFamiglie");
            //foreach (Polvere p in retValue)
            //{
            //    LookUp_FamiglieColori_ColoriAbbinati_Result r = mmm.Find(x => x.IDPolvere == p.ID);

            //    p.FamiglieColori = r.Famiglia;
            //    p.ColoriAbbinati = r.ColoriAbbinati;
            //    p.Applicazione = r.Applicazione;
            //}

            LottoFacade lf = new LottoFacade();
            foreach (ScortaMinimaInfo p in retValue)
            {

                LookUp_FamiglieColori_ColoriAbbinati_Result r = mmm.Find(x => x.IDPolvere == p.ID);

                p.FamiglieColori = r.Famiglia;
                p.ColoriAbbinati = r.ColoriAbbinati;
                p.Applicazione = r.Applicazione;

                //p.DataControllo = lf.GetDataControllo(p.ID);
                
            }
        }


        public bool ModifyScortaMinimaInfo(ScortaMinimaInfo data)
        {
            bool retValue = false;

            try
            {
                var obj = from x in context.AnagPolveri
                          where x.IDPolvere == data.ID
                          select x;

                if (obj.Any())
                {
                    AnagPolveri imp = obj.FirstOrDefault();
                    imp.CodicePolvere = data.CodicePolvere;
                    imp.Descrizione = data.Descrizione;
                    imp.Note = data.Note;
                    imp.IDFornitore = data.Fornitore.ID;
                    imp.ScortaMinima = data.ScortaMinima;
                    imp.IsCodiceCustom = data.IsCodiceCustom;

                    this.GetContext().SaveChanges();

                    retValue = true;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return retValue;
        }
    }
}
